﻿using System;
using System.Collections.Generic;
using System.Data.Entity.Spatial;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TreeManagement
{
    public class TMUtils
    {
        public static Point[] DbGeometryToPoint(DbGeometry geo)
        {
            List<Point> points = new List<Point>();
            for (int i = 0; i < geo.PointCount; i++)
            {
               
                string text = geo.WellKnownValue.WellKnownText;
                DbGeometry p = geo.PointAt(i);
                points.Add(new Point((int)p.XCoordinate,(int) p.YCoordinate));
            }
            return points.ToArray();
        }
        public static List<List<Point>> getWardPoints(TreeDBEntities context)
        {
            List<List<Point>> lstPoints = new List<List<Point>>();
            List<Ward> wards = context.Wards.ToList();
            foreach (Ward ward in wards)
            {
                int count = (int)ward.Polygon.PointCount;
                if (count > 0)
                {
                    List<Point> points = new List<Point>();
                    for (int i = 1; i <= count; i++)
                    {
                        DbGeometry geo = context.GetWardPoint(ward.ID, i).First();
                        points.Add(new Point((int)geo.XCoordinate, (int)geo.YCoordinate));
                    }
                    lstPoints.Add(points);
                }
            }
            return lstPoints;
        }
        public static List<Point> getWardPoints(TreeDBEntities context, int wardId)
        {
     
            Ward ward = context.Wards.Find(wardId);
            List<Point> points = new List<Point>();
                int count = (int)ward.Polygon.PointCount;
                if (count > 0)
                {
                   
                    for (int i = 1; i <= count; i++)
                    {
                        DbGeometry geo = context.GetWardPoint(ward.ID, i).First();
                        points.Add(new Point((int)geo.XCoordinate, (int)geo.YCoordinate));
                    }
                  
                }
            
            return points;
        }
        public static List<List<Point>> getRoadPoints(TreeDBEntities context)
        {
            List<List<Point>> lstPoints = new List<List<Point>>();
            List<Road> wards = context.Roads.ToList();
            foreach (Road ward in wards)
            {
                int count = (int)ward.Line.PointCount;
                if (count > 0)
                {
                    List<Point> points = new List<Point>();
                    for (int i = 1; i <= count; i++)
                    {
                        DbGeometry geo = context.GetRoadPoint(ward.ID, i).First();
                        points.Add(new Point((int)geo.XCoordinate, (int)geo.YCoordinate));
                    }
                    lstPoints.Add(points);
                }
            }
            return lstPoints;
        }
        public static List<Point> getTreePoint(TreeDBEntities context)
        {
            List<Point> points = new List<Point>();
            foreach (Tree tree in context.Trees)
            {
                DbGeometry geo = tree.Point;
                points.Add(new Point((int)geo.XCoordinate,(int)geo.YCoordinate));
            }
            return points;
        }
        public static double distance(Point a, Point b)
        {
            return Math.Sqrt(Math.Pow(Math.Abs(a.X - b.X), 2) + Math.Pow(Math.Abs(a.Y - b.Y), 2));
        }
        public static string addStringFromRecordedPoint(string input, Point recorded)
        {
            string delimer = ")";
            input = input.Replace(delimer, "");
            if (input == "(")
                input += recorded.X + " " + recorded.Y + delimer;
            else
                input += "," + recorded.X + " " + recorded.Y + delimer;
            return input;
        }
        public static Brush getRandomBrush(int colorIndex)
        {
            while (colorIndex >= TMConsts.POLYGON_COLORS.Length)
                colorIndex = colorIndex - TMConsts.POLYGON_COLORS.Length;
            Color color = TMConsts.POLYGON_COLORS[colorIndex];
         
            SolidBrush solidBrush1 = new SolidBrush(color);
            return solidBrush1;
        }
        public static Pen getRandomPen(int colorIndex)
        {
            while (colorIndex >= TMConsts.LINE_COLORS.Length)
                colorIndex = colorIndex - TMConsts.LINE_COLORS.Length;

            Pen solidBrush1 = new Pen(TMConsts.LINE_COLORS[colorIndex], 3);
            return solidBrush1;
        }
        public static void drawMultipleLines(Graphics g, List<List<Point>> RoadPoints)
        {
            if (RoadPoints != null)
            {
                int index = 0;
                foreach (List<Point> points in RoadPoints)
                {

                    if (points.Count > 0)
                    {
                        for (int i = 0; i < points.Count - 1; i++)
                        {
                            g.DrawLine(TMUtils.getRandomPen(index), points[i], points[i + 1]);
                        }
                        index++;
                    }
                }
            }
        }
        public static void drawLine(Graphics g, List<Point> points)
        {
            if (points == null)
                return;
            for (int i = 0; i < points.Count - 1; i++)
            {
                g.DrawLine(TMUtils.getRandomPen(0), points[i], points[i + 1]);
            }
        }
        public static void drawTreePoint(Graphics g, List<Point> points)
        {
            if (points == null)
                return;
            foreach (Point p in points)
            {
                g.DrawImage(Properties.Resources.tree_icon, new Rectangle(p.X - TMConsts.TREE_SIZE / 2, p.Y - TMConsts.TREE_SIZE / 2, TMConsts.TREE_SIZE, TMConsts.TREE_SIZE));
            }
        }
        public static void fillEclipse(Graphics g, Point p, int r)
        {
            SolidBrush semiTransBrush = new SolidBrush(Color.FromArgb(128, 0, 0, 255));
            g.FillEllipse(semiTransBrush, p.X - r, p.Y - r, r*2, r*2);
        }
        public static void drawPolygon(Graphics g, List<Point> points)
        {
            g.FillPolygon(getRandomBrush(0), points.ToArray());
        }
        public static void fillMultiplePolygons(Graphics g, List<List<Point>> WardPoints)
        {
            if (WardPoints != null)
            {
                int index = 0;
                foreach (List<Point> points in WardPoints)
                {

                    if (points.Count > 0)
                    {
                        g.FillPolygon(getRandomBrush(index), points.ToArray());
                        index++;
                    }
                }
            }
        }
        /**
         * 
         */
        public static bool checkPointsHaveCycle(List<Point> points)
        {
            if (points.Count <= 1)
                return false;
            return points[0].X == points[points.Count - 1].X && points[0].Y == points[points.Count - 1].Y;
        }
        public static Point getValidPoints(Point point, List<Point> points)
        {
            foreach (Point p in points)
            {
                if (TMUtils.distance(p, point) <= TMConsts.POINT_SIZE / 2)
                {
                    return p;
                }
            }
            return point;
        }
        public static Point getValidTree(Point point, List<Point> points)
        {
            foreach (Point p in points)
            {
                if (TMUtils.distance(p, point) <= TMConsts.TREE_SIZE / 2)
                {
                    return Point.Empty;
                }
            }
            return point;
        }
        public static bool checkPointExist(Point p, List<Point> ps)
        {
            foreach (Point po in ps)
            {
                if (po.X == p.X && po.Y == p.Y)
                    return true;
            }
            return false;
        }
    }
}
